﻿using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Text;
using Common;
using Extensions.Services.Authorization.Policys;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;

namespace Extensions.Services.Authorization;

public static class AddAuthorization
{
   // 授权 是基于验证的  所有  在controller中  特性标签验证的是解析完的token中的数据 

   public static IServiceCollection AddAuthorizationSetup(this IServiceCollection services)
   {
       if (services == null) throw new ArgumentNullException(nameof(services));

        // 以下四种常见的授权方式。

        // 1、这个很简单，其他什么都不用做， 只需要在API层的controller上边，增加特性即可
        // [Authorize(Roles = "Admin,System")]


        // 2、这个和上边的异曲同工，好处就是不用在controller中，写多个 roles 。
        // 然后这么写 [Authorize(Policy = "Admin")]
        //services.AddAuthorization(options =>
        //{
        //    options.AddPolicy("Client", policy => policy.RequireRole("Client").Build());
        //    options.AddPolicy("Admin", policy => policy.RequireRole("Admin").Build());
        //    options.AddPolicy("SystemOrAdmin", policy => policy.RequireRole("Admin", "System"));
        //    options.AddPolicy("A_S_O", policy => policy.RequireRole("Admin", "System", "Others"));
        //});
        var enable = Appsettings.app("Authentication", "Enable").ToBool();
        if (!enable)
        {
            return services;
        }

        //3.自定义授权策略
        //读取配置文件
        var iss = Appsettings.app("Authentication", "Issuer");
        var aud = Appsettings.app("Authentication", "Audience");
        var secretKey = Appsettings.app("Authentication", "Secret");
        var exp = Appsettings.app("Authentication", "Exp").ToInt32();//过期时间

        var keyByteArray = Encoding.ASCII.GetBytes(secretKey);
        var signingKey = new SymmetricSecurityKey(keyByteArray);
        var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);

        // 如果要数据库动态绑定，这里先留个空，后边处理器里动态赋值
        var permission = new List<PermissionItem>();

        // 角色与接口的权限要求参数
        var permissionRequirement = new PermissionRequirement(
            "/api/denied", // 拒绝授权的跳转地址（目前无用）
            permission,
            ClaimTypes.Role, //基于角色的授权
            iss, //发行人
            aud, //听众
            signingCredentials, //签名凭据
            expiration: TimeSpan.FromSeconds(exp) //接口的过期时间
        );
        services.AddAuthorization(options =>
       {
           options.AddPolicy(StaticConfig.PermissionName,policy=>
               policy.Requirements.Add(permissionRequirement));
       });
        // 注入httpcontext
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        // 注入权限处理器  
        services.AddScoped<IAuthorizationHandler, PermissionHandler>();
        services.AddSingleton(permissionRequirement);

        return services;
   }


}